/*  
*   This file is a part of Neutrino - a lightweight UI library accelerated with OpenGL
*   Copyright (C) 2023 bsolos
*
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include <cstddef>

namespace neutrino {
    class render_context;

    struct point {
        int x, y;
    };

    struct color {
        double r, g, b, a;
    };

    class subsurface;
    class surface {
    public:
        surface(int width, int height);
        virtual ~surface();

        virtual void clear();

        virtual void set_color(color c);
        virtual void draw_primitives(GLenum type, point points[], size_t count);

        void draw_triangle(point p1, point p2, point p3);
        void draw_line(point p1, point p2);

        virtual subsurface create_subsurface(int x, int y, int width, int height);

        int get_width();
        int get_height();

        virtual double map_x(int x);
        virtual double map_y(int y);

    protected:
        int width, height;

        virtual void send_points(point points[], size_t count);
    };


    class buffer_surface : public surface {
    public:
        buffer_surface(unsigned int fbo, GLenum buffer, int width, int height);

        void clear();

        virtual void draw_primitives(GLenum type, point points[], size_t count);

    protected:
        GLenum buffer;
        unsigned int fbo;

        void bind_buffer();
    };


    class window_surface : public buffer_surface {
    public:
        window_surface(render_context *ctx, int width, int height);

        void draw_primitives(GLenum type, point points[], size_t count);

    protected:
        render_context *ctx;
    };


    class subsurface : public surface {
    public:
        subsurface(surface *parent, int x, int y, int width, int height);

        void clear();

        void draw_primitives(GLenum type, point points[], size_t count);

        subsurface create_subsurface(int x, int y, int width, int height);

        double map_x(int x);
        double map_y(int y);
        
    protected:
        surface *parent;
        int pos_x, pos_y;
    };
}